package com.up.vms.domain.vm.service;

import com.up.vms.domain.module.ShortVideoDTO;
import com.up.vms.domain.vm.entity.ShortVideo;
import com.up.vms.domain.vm.enums.ShortVideoStatus;
import com.up.vms.domain.vm.repository.ShortVideoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class ShortVideoService {

    @Autowired
    private ShortVideoRepository shortVideoRepository;

    public Page<ShortVideo> findAllByStatus(ShortVideoDTO shortVideoDTO) {
        Sort sort = new Sort(Sort.Direction.DESC, "created");
        Pageable pageable = PageRequest.of(shortVideoDTO.getPage(), shortVideoDTO.getSize(), sort);

        return shortVideoRepository.findAllByStatus(shortVideoDTO.getStatus(), pageable);
    }

    public Page<ShortVideo> findAllByPageable(ShortVideoDTO shortVideoDTO) {
        Sort sort = new Sort(Sort.Direction.DESC, "created");
        Pageable pageable = PageRequest.of(shortVideoDTO.getPage(), shortVideoDTO.getSize(), sort);

        return shortVideoRepository.findAllByStatusLessThan(ShortVideoStatus.DELETED.code, pageable);
    }

    public ShortVideo findShortVideoById(Long shortId) {

        Optional<ShortVideo> optional =  shortVideoRepository.findById(shortId);
        if (optional.isPresent()) {
            return optional.get();
        } else {
            return null;
        }
    }

    public ShortVideo save(ShortVideo shortVideo) {
        ShortVideo newShortVideo = shortVideoRepository.save(shortVideo);
        return newShortVideo;
    }


    public Page<ShortVideo> findAllByCase(ShortVideoDTO videoDTO) {

        Sort sort = new Sort(Sort.Direction.DESC, "created");
        Pageable pageable = PageRequest.of(videoDTO.getPage(), videoDTO.getSize(), sort);

        Specification<ShortVideo> specification = new Specification<ShortVideo>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Predicate toPredicate(Root<ShortVideo> root, CriteriaQuery<?> query,
                                         CriteriaBuilder criteriaBuilder) {
                List<Predicate> lst = new ArrayList<Predicate>();


                if (videoDTO.getStatus() != null) {
                    lst.add(criteriaBuilder.equal(root.get("status"), videoDTO.getStatus()));
                } else {
                    lst.add(criteriaBuilder.lessThan(root.get("status"), ShortVideoStatus.DELETED.code));
                }

                if (videoDTO.getShortName() != null) {
                    lst.add(criteriaBuilder.like(root.get("shortName"), "%" + videoDTO.getShortName() + "%"));
                }
                if (videoDTO.getShowVideoMode() != null) {
                    lst.add(criteriaBuilder.equal(root.get("showVideoMode"), videoDTO.getShowVideoMode()));
                }
                if (videoDTO.getCategoryId() != null) {
                    lst.add(criteriaBuilder.equal(root.get("categoryId"), videoDTO.getCategoryId()));
                }
                if (videoDTO.getStartTime() != null) {
                    lst.add(criteriaBuilder.greaterThanOrEqualTo(root.get("created"), videoDTO.getStartTime()));
                }
                if (videoDTO.getEndTime() != null) {
                    lst.add(criteriaBuilder.lessThan(root.get("created"), videoDTO.getEndTime()));
                }

                return query.where(lst.toArray(new Predicate[] {})).getRestriction();

            }
        };

        return shortVideoRepository.findAll(specification, pageable);
    }

    public ShortVideo findShortVideoByIdAndCreator(Long shortId, String creator) {
        Optional<ShortVideo> optional =  shortVideoRepository.findByShortIdAndCreatorAndStatusLessThan(shortId, creator, ShortVideoStatus.DELETED.code);
        if (optional.isPresent()) {
            return optional.get();
        } else {
            return null;
        }
    }

    public void updatePlayTimes(Long id) {
        shortVideoRepository.updatePlayTimes(id);
    }
}
